package com.ssy.lingxi.search.serviceImpl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.ssy.lingxi.common.constant.CommonConstant;
import com.ssy.lingxi.common.constant.Constants;
import com.ssy.lingxi.common.exception.BusinessException;
import com.ssy.lingxi.common.model.dto.UserLoginCacheDTO;
import com.ssy.lingxi.common.response.ResponseCode;
import com.ssy.lingxi.common.response.Wrapper;
import com.ssy.lingxi.component.redis.service.IRedisStringUtils;
import com.ssy.lingxi.member.merchant.api.feign.inner.MemberLevelRightCreditControllerFeign;
import com.ssy.lingxi.member.merchant.api.model.vo.inner.request.MemberFeignBatchVO;
import com.ssy.lingxi.member.merchant.api.model.vo.inner.request.MemberFeignUpperMemberVO;
import com.ssy.lingxi.member.merchant.api.model.vo.inner.response.MemberFeignRightDetailVO;
import com.ssy.lingxi.order.api.feign.OrderFeignService;
import com.ssy.lingxi.order.api.model.vo.request.MemberAndRoleIdFeignVO;
import com.ssy.lingxi.order.api.model.vo.request.OrderFreeExpressFeignVO;
import com.ssy.lingxi.order.api.model.vo.response.OrderFreeExpressConfigVO;
import com.ssy.lingxi.search.api.model.request.SimpleIdListRequest;
import com.ssy.lingxi.search.api.model.response.LogisticsResponse;
import com.ssy.lingxi.search.entity.Commodity;
import com.ssy.lingxi.search.entity.CommodityShop;
import com.ssy.lingxi.search.entity.Logistics;
import com.ssy.lingxi.search.entity.channel.ChannelCommodityMember;
import com.ssy.lingxi.search.entity.channel.ChannelUnitPricePic;
import com.ssy.lingxi.search.entity.channel.PurchaseChannel;
import com.ssy.lingxi.search.model.response.PurchaseChannelResponse;
import com.ssy.lingxi.search.model.response.PurchaseChannelUnitPriceAndPicResponse;
import com.ssy.lingxi.search.model.response.PurchaseCommodityResponse;
import com.ssy.lingxi.search.repository.CommodityRepository;
import com.ssy.lingxi.search.repository.PurchaseChannelRepository;
import com.ssy.lingxi.search.service.IPurchaseChannelService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 进货单实现类
 * @author jw.chen
 * @version 2.0.0
 * @date 2020/6/22
 */
@Service
public class PurchaseChannelServiceImpl implements IPurchaseChannelService {

    @Resource
    private PurchaseChannelRepository purchaseChannelRepository;

    @Resource
    private CommodityRepository commodityRepository;

    @Resource
    private IRedisStringUtils redisStringUtils;

    @Resource
    private MemberLevelRightCreditControllerFeign memberFeign;

    @Resource
    private OrderFeignService orderFeignService;

    /**
     * 查询进货单列表
     */
    @Override
    public List<PurchaseChannelResponse> getPurchaseList(UserLoginCacheDTO sysUser, Long channelMemberId, Long channelMemberRoleId, Long shopId){
        List<PurchaseChannelResponse> purchaseResponseList = new ArrayList<>();
        //查询进货单
        Long memberId = sysUser.getMemberId();
        Long memberRoleId = sysUser.getMemberRoleId();
        List<PurchaseChannel> purchaseList = purchaseChannelRepository.findByMemberIdAndMemberRoleIdAndShopIdAndChannelMemberIdAndChannelMemberRoleId(memberId, memberRoleId, shopId, channelMemberId, channelMemberRoleId);
        if(purchaseList != null && !purchaseList.isEmpty()){
            //定义临时变量
            List<Long> channelCommoditySkuIdList = new ArrayList<>();
            List<MemberFeignUpperMemberVO> memberFeignUpperMemberVOList = new ArrayList<>();
            List<MemberAndRoleIdFeignVO> memberAndRoleIdFeignVOList = new ArrayList<>();
            MemberFeignBatchVO memberFeignBatchVO = new MemberFeignBatchVO();
            memberFeignBatchVO.setMemberId(memberId);
            memberFeignBatchVO.setRoleId(memberRoleId);
            //组装redis键值格式
            List<HashMap<String, String[]>> keyFieldList = purchaseList.stream().map(purchase -> {
                Long commodityUnitPriceId = purchase.getCommodityUnitPriceId();
                HashMap<String, String[]> map = new HashMap<>();
                String key = CommonConstant.FREIGHT_SPACE_REDIS_KEY + shopId + "_" + commodityUnitPriceId;
                String commodityMemberId = String.valueOf(memberId);
                map.put(key, new String[]{commodityMemberId, CommonConstant.FREIGHT_All});

                //记录所有skuId，用于查询商品
                Long channelCommodityUnitPriceId = purchase.getChannelCommodityUnitPriceId();
                channelCommoditySkuIdList.add(channelCommodityUnitPriceId);

                //记录所有供应商信息，用于查询价格权益
                MemberFeignUpperMemberVO memberFeignUpperMemberVO = new MemberFeignUpperMemberVO();
                memberFeignUpperMemberVO.setUpperMemberId(purchase.getChannelMemberId());
                memberFeignUpperMemberVO.setUpperRoleId(purchase.getChannelMemberRoleId());
                if(!memberFeignUpperMemberVOList.contains(memberFeignUpperMemberVO)){
                    memberFeignUpperMemberVOList.add(memberFeignUpperMemberVO);
                }

                //记录所有供应商信息，用于查询商品是否满额包邮
                MemberAndRoleIdFeignVO memberAndRoleIdFeignVO = new MemberAndRoleIdFeignVO();
                memberAndRoleIdFeignVO.setMemberId(purchase.getChannelMemberId());
                memberAndRoleIdFeignVO.setRoleId(purchase.getChannelMemberRoleId());
                if(!memberAndRoleIdFeignVOList.contains(memberAndRoleIdFeignVO)){
                    memberAndRoleIdFeignVOList.add(memberAndRoleIdFeignVO);
                }

                return map;
            }).collect(Collectors.toList());

            //批量查询商品信息
            HashMap<Long, Commodity> commodityHashMap = new HashMap<>();
            List<Commodity> commodityList = commodityRepository.findByMemberListUnitPricePicListIdIn(channelCommoditySkuIdList);
            commodityList.forEach(commodity -> {
                List<ChannelCommodityMember> memberList = commodity.getMemberList();
                memberList.forEach(channelCommodityMember -> {
                    List<ChannelUnitPricePic> unitPricePicList = channelCommodityMember.getUnitPricePicList();
                    unitPricePicList.forEach(unitPricePic -> {
                        commodityHashMap.put(unitPricePic.getId(), commodity);
                    });
                });
            });

            //查询价格权益
            memberFeignBatchVO.setUpperMembers(memberFeignUpperMemberVOList);
            HashMap<String, BigDecimal> memberMap = new HashMap<>();
            try{
                Wrapper<List<MemberFeignRightDetailVO>> listWrapper = memberFeign.batchMemberPriceRight(memberFeignBatchVO);
                if(listWrapper != null && listWrapper.getCode() == ResponseCode.SUCCESS.getCode()){
                    List<MemberFeignRightDetailVO> data = listWrapper.getData();
                    data.forEach(memberFeignRightDetailVO -> {
                        String member = memberFeignRightDetailVO.getUpperMemberId() + "_" + memberFeignRightDetailVO.getUpperRoleId();
                        memberMap.put(member, memberFeignRightDetailVO.getParameter());
                    });
                }
            }catch (Exception e){
                e.printStackTrace();
            }

            //查询供应商商品是否满额包邮
            OrderFreeExpressFeignVO orderFreeExpressFeignVO = new OrderFreeExpressFeignVO();
            orderFreeExpressFeignVO.setItemList(memberAndRoleIdFeignVOList);
            HashMap<String, BigDecimal> orderFreeExpressMap = new HashMap<>();
            try{
                Wrapper<List<OrderFreeExpressConfigVO>> listWrapper = orderFeignService.getOrderFreeExpressConfigList(orderFreeExpressFeignVO);
                if(listWrapper != null && listWrapper.getCode() == ResponseCode.SUCCESS.getCode()){
                    List<OrderFreeExpressConfigVO> data = listWrapper.getData();
                    data.forEach(orderFreeExpressConfigVO -> {
                        String member = orderFreeExpressConfigVO.getMemberId() + "_" + orderFreeExpressConfigVO.getRoleId();
                        orderFreeExpressMap.put(member, orderFreeExpressConfigVO.getOrderAmount());
                    });
                }
            }catch (Exception e){
                e.printStackTrace();
            }

            //获取库存数据并赋值给每个进货单
            List<Object> resultList = redisStringUtils.hMGetBatch(keyFieldList, Constants.REDIS_PRODUCT_INDEX);
            for(int i = 0; i < purchaseList.size(); i++){
                PurchaseChannelResponse purchaseChannelResponse = new PurchaseChannelResponse();
                PurchaseChannel purchase = purchaseList.get(i);
                BeanUtil.copyProperties(purchase, purchaseChannelResponse);
                //计算当前商品的库存数
                List<String> stockList = (List<String>)resultList.get(i);
                if(stockList != null && !stockList.isEmpty()){
                    List<String> collect = stockList.stream().filter(StrUtil::isNotEmpty).collect(Collectors.toList());
                    if(!collect.isEmpty()){
                        Double stockCount = collect.stream().map(Double::parseDouble).reduce(Double::sum).get();
                        purchaseChannelResponse.setStockCount(stockCount);
                    }
                }
                Long commodityUnitPriceId = purchase.getChannelCommodityUnitPriceId();
                Commodity commodity = commodityHashMap.get(commodityUnitPriceId);
                if(commodity != null){
                    commodity.getMemberList().forEach(channelCommodityMember -> channelCommodityMember.getUnitPricePicList().forEach(unitPricePic -> {
                        Long unitPricePicId = unitPricePic.getId();
                        if(unitPricePicId.equals(commodityUnitPriceId)){
                            PurchaseChannelUnitPriceAndPicResponse purchaseUnitPriceAndPicResponse = new PurchaseChannelUnitPriceAndPicResponse();
                            BeanUtil.copyProperties(unitPricePic, purchaseUnitPriceAndPicResponse);
                            PurchaseCommodityResponse purchaseCommodityResponse = new PurchaseCommodityResponse();
                            BeanUtil.copyProperties(commodity, purchaseCommodityResponse);
                            //设置会员信息
                            purchaseCommodityResponse.setMemberId(channelCommodityMember.getChannelMemberId());
                            purchaseCommodityResponse.setMemberName(channelCommodityMember.getChannelMemberName());
                            purchaseCommodityResponse.setMemberRoleId(channelCommodityMember.getChannelMemberRoleId());
                            purchaseCommodityResponse.setStoreId(channelCommodityMember.getStoreId());
                            purchaseCommodityResponse.setIsMemberPrice(channelCommodityMember.getIsMemberPrice());
                            Logistics logistics = channelCommodityMember.getLogistics();

                            purchaseCommodityResponse.setLogistics(BeanUtil.copyProperties(logistics, LogisticsResponse.class));
                            purchaseUnitPriceAndPicResponse.setCommodity(purchaseCommodityResponse);
                            purchaseChannelResponse.setCommodityUnitPrice(purchaseUnitPriceAndPicResponse);
                            purchaseChannelResponse.setChannelCommodityId(channelCommodityMember.getId());

                            List<Long> shopList = channelCommodityMember.getShopList().stream().map(CommodityShop::getShopId).collect(Collectors.toList());
                            if(shopList.size() > 0){
                                purchaseChannelResponse.setIsPublish(shopList.contains(shopId));
                            }else{
                                purchaseChannelResponse.setIsPublish(false);
                            }
                        }
                    }));

                    //获取价格权益
                    BigDecimal bigDecimal = memberMap.get(purchase.getChannelMemberId() + "_" + purchase.getChannelMemberRoleId());
                    if(bigDecimal != null && bigDecimal.compareTo(BigDecimal.ZERO) > 0){
                        purchaseChannelResponse.setParameter(bigDecimal);
                    }else{
                        purchaseChannelResponse.setParameter(BigDecimal.valueOf(1L));
                    }

                    //获取供应商商品是否满额包邮
                    BigDecimal orderAmount = orderFreeExpressMap.get(commodity.getMemberId() + "_" + commodity.getMemberRoleId());
                    if(orderAmount != null && orderAmount.compareTo(BigDecimal.ZERO) > 0){
                        purchaseChannelResponse.setOrderAmount(orderAmount);
                    }

                    purchaseResponseList.add(purchaseChannelResponse);
                }
            }
            return purchaseResponseList;
        }else{
            return new ArrayList<>();
        }
    }

    /**
     * 添加/修改进货单
     * @param purchaseChannel
     * @return
     */
    @Override
    public Integer saveOrUpdatePurchase(UserLoginCacheDTO sysUser, PurchaseChannel purchaseChannel){
        Long id = purchaseChannel.getId();
        Long shopId = purchaseChannel.getShopId();
        Long unitPriceAndPicId = purchaseChannel.getCommodityUnitPriceId();
        Long channelCommodityUnitPriceId = purchaseChannel.getChannelCommodityUnitPriceId();
        Long channelMemberId = purchaseChannel.getChannelMemberId();
        Long channelMemberRoleId = purchaseChannel.getChannelMemberRoleId();
        //判断是新增还是修改
        if(id != null && id > 0){
            //验证数据库中是否存在该数据
            PurchaseChannel oldPurchase = purchaseChannelRepository.findById(id).orElse(null);
            if(oldPurchase != null) {
                Long oldShopId = oldPurchase.getShopId();
                if (shopId.longValue() == oldShopId.longValue()) {
                    double count = purchaseChannel.getCount();
                    Long commodityUnitPriceId = oldPurchase.getCommodityUnitPriceId();
                    double stock = this.getStock(sysUser.getMemberId(), shopId, commodityUnitPriceId);
                    if(count <= stock){
                        oldPurchase.setCount(count);
                        purchaseChannelRepository.saveAndFlush(oldPurchase);
                        return purchaseChannelRepository.countByMemberIdAndMemberRoleIdAndShopIdAndChannelMemberIdAndChannelMemberRoleId(sysUser.getMemberId(), sysUser.getMemberRoleId(), shopId, channelMemberId, channelMemberRoleId);
                    }else{
                        throw new BusinessException(ResponseCode.PRODUCT_COMMODITY_PASS_STOCK);
                    }
                }
            }
            throw new BusinessException(ResponseCode.PRODUCT_PURCHASE_NOT_EXIST);
        }else{
            //检查商品规格
            if(unitPriceAndPicId != null && unitPriceAndPicId > 0){
                PurchaseChannel oldPurchase = purchaseChannelRepository.findFirstByMemberIdAndMemberRoleIdAndCommodityUnitPriceIdAndShopIdAndChannelMemberIdAndChannelMemberRoleId(sysUser.getMemberId(), sysUser.getMemberRoleId(), unitPriceAndPicId, shopId, channelMemberId, channelMemberRoleId);
                if(oldPurchase != null){
                    double count = oldPurchase.getCount() + purchaseChannel.getCount();
                    double stock = this.getStock(sysUser.getMemberId(), shopId, unitPriceAndPicId);
                    if(count <= stock) {
                        oldPurchase.setCount(count);
                    }else{
                        throw new BusinessException(ResponseCode.PRODUCT_COMMODITY_PASS_STOCK);
                    }
                }else{
                    Integer purchaseMaxCount = Constants.PURCHASE_MAX_COUNT;
                    Integer existCount = purchaseChannelRepository.countByMemberIdAndMemberRoleIdAndShopIdAndChannelMemberIdAndChannelMemberRoleId(sysUser.getMemberId(), sysUser.getMemberRoleId(), shopId, channelMemberId, channelMemberRoleId);
                    if(existCount >= purchaseMaxCount){
                        throw new BusinessException(ResponseCode.PRODUCT_PURCHASE_COUNT_OUT);
                    }
                    double count = purchaseChannel.getCount();
                    double stock = this.getStock(sysUser.getMemberId(), shopId, unitPriceAndPicId);
                    if(count <= stock) {
                        oldPurchase = new PurchaseChannel();
                        //数据库持久化对象
                        oldPurchase.setCount(count);
                        oldPurchase.setShopId(shopId);
                        oldPurchase.setChannelMemberId(channelMemberId);
                        oldPurchase.setChannelMemberRoleId(channelMemberRoleId);
                        oldPurchase.setCommodityUnitPriceId(unitPriceAndPicId);
                        oldPurchase.setChannelCommodityUnitPriceId(channelCommodityUnitPriceId);
                        oldPurchase.setMemberId(sysUser.getMemberId());
                        oldPurchase.setMemberName(sysUser.getCompany());
                        oldPurchase.setMemberRoleId(sysUser.getMemberRoleId());
                        oldPurchase.setMemberRoleName(sysUser.getMemberRoleName());
                        oldPurchase.setUserId(sysUser.getUserId());
                        oldPurchase.setUserName(sysUser.getUserName());
                    }else{
                        throw new BusinessException(ResponseCode.PRODUCT_COMMODITY_PASS_STOCK);
                    }
                }
                purchaseChannelRepository.saveAndFlush(oldPurchase);
                return this.getPurchaseCount(sysUser, shopId, purchaseChannel.getChannelMemberId(), purchaseChannel.getChannelMemberRoleId());
            }
            throw new BusinessException(ResponseCode.PRODUCT_PURCHASE_UNITPRICE_NOT_EXIST);
        }
    }

    /**
     * 删除进货单
     * @param simpleIdListRequest
     * @return
     */
    @Override
    public String deletePurchase(SimpleIdListRequest simpleIdListRequest) {
        //验证数据库中是否存在该数据
        List<Long> idList = simpleIdListRequest.getIdList();
        List<PurchaseChannel> purchaseList = purchaseChannelRepository.findByIdIn(idList);
        if(purchaseList != null && purchaseList.size() == idList.size()){
            purchaseChannelRepository.deleteAll(purchaseList);
            return ResponseCode.SUCCESS.getMessage();
        }
        throw new BusinessException(ResponseCode.PRODUCT_PURCHASE_NOT_EXIST);
    }

    /**
     * 查询进货单数量
     * @param sysUser
     * @return
     */
    @Override
    public Integer getPurchaseCount(UserLoginCacheDTO sysUser, Long shopId, Long channelMemberId, Long channelMemberRoleId) {
        Long loginMemberId = sysUser.getMemberId();
        Long loginMemberRoleId = sysUser.getMemberRoleId();
        List<PurchaseChannel> purchaseChannelList = purchaseChannelRepository.findByMemberIdAndMemberRoleIdAndShopIdAndChannelMemberIdAndChannelMemberRoleId(loginMemberId, loginMemberRoleId, shopId, channelMemberId, channelMemberRoleId);
        List<Long> channelCommoditySkuIdList = purchaseChannelList.stream().map(PurchaseChannel::getChannelCommodityUnitPriceId).collect(Collectors.toList());
        //批量查询商品信息
        HashMap<Long, ChannelCommodityMember> commodityHashMap = new HashMap<>();
        List<Commodity> commodityList = commodityRepository.findByMemberListUnitPricePicListIdIn(channelCommoditySkuIdList);
        commodityList.forEach(commodity -> {
            List<ChannelCommodityMember> memberList = commodity.getMemberList();
            memberList.forEach(channelCommodityMember -> {
                List<ChannelUnitPricePic> unitPricePicList = channelCommodityMember.getUnitPricePicList();
                unitPricePicList.forEach(unitPricePic -> commodityHashMap.put(unitPricePic.getId(), channelCommodityMember));
            });
        });
        //过滤掉那些关联不到商品的进货单
        return (int) purchaseChannelList.stream().map(purchaseChannel -> commodityHashMap.get(purchaseChannel.getChannelCommodityUnitPriceId())).filter(Objects::nonNull).count();
    }

    /**
     * 查询商品的库存
     * @param memberId
     * @param shopId
     * @param commodityUnitPriceId
     * @return
     */
    private double getStock(Long memberId, Long shopId, Long commodityUnitPriceId){
        //查询库存
        String key = CommonConstant.FREIGHT_SPACE_REDIS_KEY + shopId + "_" + commodityUnitPriceId;
        String[] fields = new String[]{String.valueOf(memberId), CommonConstant.FREIGHT_All};
        List<String> list = redisStringUtils.hMGet(key, fields, Constants.REDIS_PRODUCT_INDEX);
        return list.stream().filter(Objects::nonNull).map(Double::parseDouble).reduce(Double::sum).orElse(0.0);
    }
}

